﻿using System;

namespace Cpu6502.Opcodes
{
    public class CMP_I : Opcode
    {
        public CMP_I()
        {
            this.CpuCycles = 2;
            this.AddressType = CPU.AddressType.Immediate;
        }
        public override void Execute()
        {
            int data = base.Argument;

            data = (CPU.Registers.A - data);
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    public class CMP_A : Opcode
    {
        public CMP_A()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.Absolute;
        }
        public override void Execute()
        {
            int data = 
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument,CPU.AddressType.Absolute)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    public class CMP_A_X : Opcode
    {
        public CMP_A_X()
        {
            // TODO: If Crossing a page make this 5
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedX;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.AbsoluteIndexedX)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    public class CMP_A_Y : Opcode
    {
        public CMP_A_Y()
        {
            // TODO: If Crossing a page make this 5
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.AbsoluteIndexedY;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.AbsoluteIndexedY)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    public class CMP_ZP : Opcode
    {
        public CMP_ZP()
        {            
            this.CpuCycles = 3;
            this.AddressType = CPU.AddressType.ZeroPage;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.ZeroPage)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    public class CMP_ZP_X : Opcode
    {
        public CMP_ZP_X()
        {
            this.CpuCycles = 4;
            this.AddressType = CPU.AddressType.ZeroPageIndexedX;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.ZeroPageIndexedX)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    /// <summary>
    /// CMP ($AA,X)
    /// </summary>
    public class CMP_Indexed_Indirect : Opcode
    {
        public CMP_Indexed_Indirect()
        {
            this.CpuCycles = 6;
            this.AddressType = CPU.AddressType.IndexedIndirect;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.IndexedIndirect)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }

    /// <summary>
    /// CMP ($AA), Y
    /// </summary>
    public class CMP_Indirect_Indexed : Opcode
    {
        public CMP_Indirect_Indexed()
        {
            // TODO: Increase if crossing page
            this.CpuCycles = 5;
            this.AddressType = CPU.AddressType.IndirectIndexed;
        }
        public override void Execute()
        {
            int data =
                CPU.Memory
                [
                    MemoryHelper.GetAddress
                    (base.Argument, CPU.AddressType.IndirectIndexed)
                ];

            data = CPU.Registers.A - data;
            CPU.Registers.P.C = (data < 0x100);
            CPU.Registers.P.N = (((data << 7) & 1) != 0);
            CPU.Registers.P.Z = ((data &= 0xff) == 0);
        }
    }
}
